"""builtins compatibility layer"""

try:
    all  # New in 2.5
except NameError:
    def all(iterable):
        for element in iterable:
            if not element:
                return False
        return True

try:
    any  # New in 2.5
except NameError:
    def any(iterable):
        for element in iterable:
            if element:
                return True
        return False

try:
    next  # New in 2.6
except NameError:
    def next(iterator):
        return iterator.next()

# In the move to Python 3.0, map, filter, zip were replaced with their
# iterable equivalents from the itertools module.
try:
    map.__iter__
    filter.__iter__
    zip.__iter__
except AttributeError:
    # Import directly from itertools (NOT through compatibility layer).
    from itertools import imap    as map
    from itertools import ifilter as filter
    from itertools import izip    as zip

try:
    range.__iter__
except AttributeError:
    range = xrange

try:
    property.setter  # New in 2.6
except AttributeError:
    # Code taken from cpython/Doc/howto/descriptor.rst source file.
    # The setter and deleter methods were added as well as other small
    # changes for 3to2 compatibility.
    class property(object):

        def __init__(self, fget=None, fset=None, fdel=None, doc=None):
            self.fget = fget
            self.fset = fset
            self.fdel = fdel
            self.__doc__ = doc

        def __get__(self, obj, objtype=None):
            if obj is None:
                return self
            if self.fget is None:
                raise AttributeError("unreadable attribute")
            return self.fget(obj)

        def __set__(self, obj, value):
            if self.fset is None:
                raise AttributeError("can't set attribute")
            self.fset(obj, value)

        def __delete__(self, obj):
            if self.fdel is None:
                raise AttributeError("can't delete attribute")
            self.fdel(obj)

        def setter(self, func):
            self.fset = func
            return self

        def deleter(self, func):
            self.fdel = func
            return self

try:
    callable  # Removed from 3.0 and 3.1, added back in 3.2.
except NameError:
    def callable(obj):
        parent_types = type(obj).__mro__
        return any('__call__' in typ.__dict__ for typ in parent_types)
